package com.ljy.job.task;

import com.ljy.job.component.MySeleniumDownloader;
import com.ljy.job.domain.JobInfo;
import com.ljy.job.service.JobInfoService;
import lombok.extern.slf4j.Slf4j;
import org.jsoup.Jsoup;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import us.codecraft.webmagic.Page;
import us.codecraft.webmagic.Site;
import us.codecraft.webmagic.Spider;
import us.codecraft.webmagic.processor.PageProcessor;
import us.codecraft.webmagic.selector.Html;
import us.codecraft.webmagic.selector.Selectable;

import java.util.List;

/**
 * @program: webMagic-job
 * @description: 定时抓取51job
 * @author: liangjiayy
 * @create: 2022-01-29 21:49
 **/
@Component
@Slf4j
public class JobProcessor implements PageProcessor {
    @Autowired
    private JobInfoService service;
    @Autowired
    JobProcessor jobProcessor;

    @Override
    public void process(Page page) {
        String url = page.getUrl().get();
        if (url.startsWith("https://jobs.51job.com")){
            //是详情页
            log.info("详情页{}",url);
            //解析封装数据
            JobInfo jobInfo = parse(page);
            //存数据库
            log.info("保存的结果：{}",service.save(jobInfo));
        }else if (url.startsWith("https://search.51job.com")){
            log.info("列表页{}",url);

            List<Selectable> jobNodes = page.getHtml().css("div.j_joblist > div").nodes();
            //是列表页
            for (Selectable jobNode : jobNodes) {
                //解析详情页地址
                String href = jobNode.css("div > a", "href").get();
                //放入目标
                page.addTargetRequest(href);
            }
            // 判断是否有下一页
            List<String> all = page.getHtml().css("li.next:not(.bk)").all();//有.bk标签的是最后一页
            if (all.size() > 0){//有下一页
                //下一页的数据
                String nextPageUrl = getNextPageUrl(page.getUrl().toString());
                page.addTargetRequest(nextPageUrl);
            }

        }
        else {
            log.error("未知页面{}",url);
        }
    }

    public String getNextPageUrl(String url) {
        //获取当前页码 https://search.51job.com/list/200200,000000,0121,32%252c01,9,99,java,2,1.html?lang=c&postchannel=0000&workyear=99&cotype=99&degreefrom=99&jobterm=99&companysize=99&ord_field=0&dibiaoid=0&line=&welfare=
        int end = url.indexOf(".html?");// 当前页码后一个字符串的位置
        String sub = url.substring(0, end);// .html之前的部分
        int begin = sub.lastIndexOf(",");// 当前页码的前一个","的位置
        long pageNumber = Long.parseLong(sub.substring(begin + 1));//当前页码
        //替换为新页码
        return url.replace(pageNumber + ".html", (pageNumber + 1) + ".html");
    }

    private JobInfo parse(Page page) {
        Html html = page.getHtml();

        JobInfo jobInfo = new JobInfo();
        // 公司联系方式
        jobInfo.setCompanyAddr(Jsoup.parse(html.css("div.bmsg.inbox > p.fp").get()).text());
        // 公司名
        jobInfo.setCompanyName(html.css("p.cname > a.catn","title").get());
        // 公司信息
        jobInfo.setCompanyInfo(html.css("div.tmsg.inbox").get());
        // 工作地点
        String p_msg_ltype = html.css("div.cn > p.msg.ltype").get();
        String[] split = Jsoup.parse(p_msg_ltype).text().split("\\|");
        jobInfo.setJobAddr(split[0]);
        // 职位名称
        jobInfo.setJobName(html.css("h1","title").get());
        // 职位信息
        jobInfo.setJobInfo(html.css("div.bmsg.job_msg.inbox").get());
        // 薪水
        String salary = Jsoup.parse(html.css("div.cn > strong").get()).text();
        int[] salary_minMax = parseSalary(salary);
        jobInfo.setSalaryMin(salary_minMax[0]);
        jobInfo.setSalaryMax(salary_minMax[1]);
        // 详情页
        jobInfo.setUrl(page.getUrl().get());
        // 最近发布时间
        jobInfo.setTime(split[4]);

        //log.info("工作信息：\n{}",jobInfo);
        return jobInfo;
    }

    private int[] parseSalary(String salary) {
        try {
            // 1.1-2.1千/月  千/年  万/月  万/年
            salary = salary.replaceAll(" ","");
            int len = salary.length();
            String[] minMax = salary.substring(0, len - 3).split("-");
            double min = Double.parseDouble(minMax[0]);
            double max = Double.parseDouble(minMax[1]);

            String[] danWei = salary.substring(len-3).split("/");
            // 转化为 元/月
            if ("千".equals(danWei[0])){
                min *= 1000;
                max *= 1000;
            }else if("万".equals(danWei[0])){
                min *= 10000;
                max *= 10000;
            }else {
                throw new RuntimeException("薪水上下界转换出错");
            }

            if("年".equals(danWei[1])){
                min /= 12.0;
                max /= 12.0;
            }else if ("月".equals(danWei[1])){

            }else {
                throw new RuntimeException("单位转换出错");
            }

            return new int[]{(int)min,(int)max};
        } catch (Exception e) {
            log.info("{} 未转换成功,最低最高薪水均设置为0;错误原因:{}",salary,e.getMessage());
            return new int[]{0,0};
        }
    }

    @Override
    public Site getSite() {
        return Site.me()
                .setUserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36")
                //.setCharset("gbk")
                .setTimeOut(30*1000)
                .setSleepTime(5*1000)
                //重试次数
                .setCycleRetryTimes(3);
    }
    @Scheduled(fixedDelay = 100*1000,initialDelay = 2000)//fixedDelay：每隔多久执行方法，initialDelay:任务启动后多久开始执行方法
    public void run(){
        System.setProperty("selenuim_config", "C:\\Users\\AikeTech\\IdeaProjects\\webMagic-job\\src\\main\\resources\\selenium.ini");

        Spider.create(jobProcessor)
                .addUrl("https://search.51job.com/list/200200,000000,0121,32%252c01,9,99,java,2,4.html?lang=c&postchannel=0000&workyear=99&cotype=99&degreefrom=99&jobterm=99&companysize=99&ord_field=0&dibiaoid=0&line=&welfare=")
                .thread(3)
                .setDownloader(new MySeleniumDownloader("C:\\Users\\AikeTech\\ljy\\driver\\chromedriver\\chromedriver.exe"))
                .run();
    }
}
